
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>4、JDBC批量处理 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>4、JDBC批量处理 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">什么是JDBC批量处理，它主要解决了什么问题？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">JDBC批量处理是指将多个数据库操作（如插入、更新、删除）打包在一个请求中一次性提交到数据库。它主要解决了因逐条执行SQL语句而导致的数据库负载迅速增加和网络延迟成为瓶颈的问题，通过显著减少与数据库的交互次数来提高数据操作效率。</div>
          </div>
          <div class="card-source">来源: JDBC批量处理 / 批量处理的基本概念</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">在JDBC中，使用`PreparedStatement`实现批量处理的核心步骤是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">1. 创建`PreparedStatement`对象，并传入参数化的SQL语句。<br>2. 循环中使用`setXXX()`方法为SQL语句设置参数。<br>3. 每次设置完参数后，调用`addBatch()`方法将该条SQL语句添加到批量队列中。<br>4. 循环结束后，调用`executeBatch()`方法一次性执行队列中的所有SQL语句。</div>
          </div>
          <div class="card-source">来源: JDBC批量处理的基本方法 > 2. 使用 PreparedStatement 执行批量处理</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">优化</div>
          <div class="card-question">为什么在进行JDBC批量处理时，通常建议禁用数据库连接的自动提交（AutoCommit）模式？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">优化</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">因为在默认的自动提交模式下，每执行一条SQL语句都会自动提交一次事务，这会产生不必要的事务开销。禁用自动提交（`connection.setAutoCommit(false)`）并手动管理事务，可以在所有批量操作成功后通过一次`commit()`提交，从而减少事务次数，提高性能，并确保整个批量操作的原子性。</div>
          </div>
          <div class="card-source">来源: JDBC批量处理的优化 > 3. 使用事务进行批量操作</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">JDBC中的`executeBatch()`和`executeLargeBatch()`方法有何区别，应在什么场景下选择后者？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">主要区别在于返回值类型。`executeBatch()`返回一个`int[]`数组，而`executeLargeBatch()`返回一个`long[]`数组。当处理非常大的批量操作（例如上百万条数据），其影响的行数可能超过`int`类型的最大值时，应该使用`executeLargeBatch()`来避免数据溢出。</div>
          </div>
          <div class="card-source">来源: JDBC批量处理的基本方法 > 3. 使用 executeLargeBatch() 执行大批量操作</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">根据文档，JDBC批量处理能带来哪些具体优势？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">JDBC批量处理主要有三大优势：<br>1.  **提高性能**：通过减少与数据库的交互次数和避免频繁开关连接来提升数据处理速度。<br>2.  **减少网络延迟**：批量提交减少了网络传输的次数，从而降低了延迟。<br>3.  **减少数据库负载**：数据库通常会对批量请求进行优化，处理大规模数据时更高效，从而降低资源消耗。</div>
          </div>
          <div class="card-source">来源: 批量处理的基本概念 > 1. 批量处理的优势</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">优化</div>
          <div class="card-question">在进行大规模批量插入时，除了代码层面的优化，还可以从数据库层面采取哪些措施来提升性能？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">优化</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">可以采取两种数据库层面的优化措施：<br>1.  **减少不必要的数据库索引**：在批量插入前暂时禁用或删除不必要的索引，待插入完成后再重新创建，以避免每次插入都更新索引带来的开销。<br>2.  **禁用外键约束**：批量插入前禁用外键约束（`SET foreign_key_checks = 0;`），完成后再启用，以避免数据库对每条记录进行约束检查。</div>
          </div>
          <div class="card-source">来源: JDBC批量处理的高级技巧</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">在实现JDBC批量处理时，如何合理地设置“批量大小”（Batch Size）？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">批量大小不宜过大或过小。过大会导致内存溢出或数据库I/O瓶颈，过小则无法充分利用批量处理的优势。文档建议设置一个合适的大小（通常为500到1000条记录），并在代码中通过循环和条件判断（如 `i % batchSize == 0`）来分批次执行`executeBatch()`，以平衡内存消耗和性能。</div>
          </div>
          <div class="card-source">来源: JDBC批量处理的优化 > 1. 合理设置批量大小</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">相比`Statement`，使用`PreparedStatement`进行批量处理有哪些优点？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`PreparedStatement`更适合批量处理，主要优点有：<br>1.  **性能更优**：SQL语句被预编译，在处理参数化的批量操作时，可以复用执行计划，减少编译开销。<br>2.  **安全性更高**：能够有效避免SQL注入攻击。<br>3.  **适用性更广**：适用于SQL结构相同但参数值动态变化的批量场景。</div>
          </div>
          <div class="card-source">来源: JDBC批量处理的优化 > 4. 使用 PreparedStatement 而不是 Statement</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">在JDBC批量处理中，如何利用事务来保证数据的一致性，尤其是在发生错误时？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">通过手动事务管理来保证一致性。首先通过`connection.setAutoCommit(false)`禁用自动提交。然后，将批量执行代码（`executeBatch()`）和提交操作（`connection.commit()`）放入`try`代码块中。在对应的`catch (SQLException e)`代码块中，调用`connection.rollback()`方法。这样，如果批量操作中有任何一条语句失败，整个事务就会被回滚，确保数据不会处于部分更新的状态。</div>
          </div>
          <div class="card-source">来源: JDBC批量处理的基本方法 > 4. 批量操作的事务管理</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
